package com.dfbz.demo02_自定义类加载器;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

// 1. 继承 ClassLoader
// 2. 覆盖 findClass方法
public class MyClassLoader extends ClassLoader {

    // 被加载类所在的目录
    private String dir;

    public MyClassLoader(String dir) {          // 默认父类加载器就是系统类加载器 AppClassLoader
        this.dir = dir;
    }

    public MyClassLoader(ClassLoader parent, String dir) {
        super(parent);
        this.dir = dir;
    }

    /**
     *
     * @param name
     * @return 重写findClass方法
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            // 把类名转换为目录  --->  D:/000/com/dfbz/demo01/Show.class
            String file = dir + "/" + name.replace(".", "/") + ".class";

            // 从文件中读取这个Class文件
            InputStream in = new FileInputStream(file);

            // 构建一个内存输出流(将读取到的Class文件写在内存中)
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            byte[] buf = new byte[1024];

            int len ;

            while ((len = in.read(buf)) != -1) {
                baos.write(buf, 0, len);
            }

            // 读取到的流的二进制数据
            byte[] data = baos.toByteArray();
            in.close();
            baos.close();

            /*
            defineClass: 根据类的全包名和内存中的数据流来加载一个类
             - 参数1: 需要加载类的全包名
             - 参数2: 已经加载到内存中的数据流
             - 参数3: 从指定的数据下表开始读取
             - 参数4: 读取到什么位置
             */
            return defineClass(name, data, 0, data.length);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}